/** \file    timing_xml.cpp
  * \brief   Gives a means for timing a program with details for routines call-tree.
  * \date    2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/mswin/src/timing_xml.cpp,v 1.3 2006/02/24 17:47:46 cscom1r4 Exp $
  */

#include "mswin/timing.h"
#include "timing_node.h"
#include "xml/stream.h"
#include <algorithm>

namespace xml { 

stream & operator || (stream & s, mswin::node & t);

struct out {
	out(stream & s) : _s(s) 
		{}
	void operator ()(mswin::node & t)
		{ _s || child("node", t); }
private:
	stream & _s;
};

struct in {
	in(mswin::node & t) : _t(t) 
		{}
	void operator ()(const node & n) {
		stream s(n, true);
		std::string name;
		s || attr("name", name);
		s || (*_t.open(name));
	}
private:
	mswin::node & _t;
};

stream & operator || (stream & s, mswin::node & t)
{
	s || def_attr("name", t.name, std::string("root"));
	s || def_attr("calls_count", t.calls_count);
	s || def_attr("node_time", t.node_time);
	s || def_attr("subtree_time", t.subtree_time, t.node_time);
	s || def_attr("node_count", t.node_count.QuadPart);
	s || def_attr("subtree_count", t.subtree_count.QuadPart, t.node_count.QuadPart);

	if (s.out())
		t.for_each_child(out(s));
	else {
		node_list nlist;
		s.root().children(nlist, "node");
		std::for_each(nlist.begin(), nlist.end(), in(t));
	}

	return s;
}

stream & operator || (stream & s, mswin::timing_tree & t)
{
	assert(t._current == t._root);

	LARGE_INTEGER freq;
	QueryPerformanceFrequency(&freq);
	s || def_in_attr("frequency", freq.QuadPart, LONGLONG(0));

	return s || *t._root;
}

} //namespace xml
